/*******************************************************************************
 * Copyright (c) 2010 liw.
 * All rights reserved. 
 * 
 * This file is part of VanBus.
 * 
 *     VanBus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     VanBus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with VanBus.  If not, see <http://www.gnu.org/licenses/>.
 * Contributors:
 *     liw - initial API and implementation
 ******************************************************************************/
package org.niclab.vanbus.activity.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.niclab.vanbus.R;
import org.niclab.vanbus.activity.StopListOfRouteAct;
import org.niclab.vanbus.application.VanBusApplication;
import org.niclab.vanbus.database.ApplicationDataBase;
import org.niclab.vanbus.database.BusRouteDAO;
import org.niclab.vanbus.database.BusStopDAO;
import org.niclab.vanbus.model.BusRoute;
import org.niclab.vanbus.model.BusStop;
import org.niclab.vanbus.model.viewadpater.BusStopArrayAdapter;
import org.niclab.vanbus.query.ClosestBusStopsQuery;
import org.niclab.vanbus.query.IQuery;
import org.niclab.vanbus.query.RouteStopsWithTimesQuery;
import org.niclab.vanbus.query.SimpleQueryWorker;
import org.niclab.vanbus.query.command.ClosestStopsByRouteUICmd;
import org.niclab.vanbus.query.command.ICommand;
import org.niclab.vanbus.query.command.ICommandChain;
import org.niclab.vanbus.query.command.ToggleBusyLoadingPanelCmd;
import org.niclab.vanbus.query.command.UpdateListViewCmd;
import org.niclab.vanbus.query.handler.IQueryHandler;
import org.niclab.vanbus.query.mem.SimpleMemQueryHandler;
import org.niclab.vanbus.query.ws.ClosestBusStopsWSQueryResResolver;
import org.niclab.vanbus.query.ws.RouteStopsWithTimesWSQueryResResolver;
import org.niclab.vanbus.query.ws.SimpleWSQueryHandler;
import org.niclab.vanbus.utils.CacheUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.location.Location;
import android.util.Log;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.ListView;


public class BusRouteController {
	
	private final static String LOG_TAG="BusRouteController";
	
	private BusRoute busRoute;
	

	public BusRouteController(){
		
	}
	public BusRouteController(BusRoute route){
		
		this.busRoute = route;
	
		
	}


	public void setBusRoute(BusRoute busRoute) {
		this.busRoute = busRoute;
	}

	/**
	 * 
	 * @param routeId route Id
	 * @param routeDir direction
	 * @param routeName name
	 * @param routeDirDesp direction description
	 *
	 * @return BusRoute object
	 */

	public BusRoute createBusRouteFromCache(String routeId, String routeDir, String routeName, String routeDirDesp){
		BusRoute route = null;
		if(routeId !=null && routeDir!=null)
			route=CacheUtils.getCachedBusRoute(routeId, routeDir);
		if(route == null){
			route = new BusRoute();
			route.setRouteId(routeId);
			route.setRouteDir(routeDir);
			route.setRouteDirDesp(routeDirDesp);
			route.setRouteName(routeName);
		}
		
		return route;
		
	}
	
	
	
	
	public BusRoute createBusRouteFromCacheAndDB(Cursor cursor){
		
		String routeId = cursor.getString(cursor.getColumnIndex("ROUTE_ID"));
		String routeDir = cursor.getString(cursor.getColumnIndex("DIR"));
		
		BusRoute route = CacheUtils.getCachedBusRoute(routeId, routeDir);
		
		if(route==null){
			BusRouteDAO routeDAO = new BusRouteDAO(ApplicationDataBase.getSQLiteOpenHelper());
			route = routeDAO.getBusRoute(cursor);
		}
		
		return route;
			
	
		
	}
	public void saveBusRouteToCache(BusRoute route){
		
		CacheUtils.saveBusRouteToCache(route);
	}

	
	public void cancelFavoriteRoute(Context context) {
		busRoute.setFavorite(false);
		BusRouteDAO routeDAO = new BusRouteDAO(ApplicationDataBase.getSQLiteOpenHelper());
		routeDAO.unsetFavorite(busRoute);
		context.sendBroadcast(new Intent(context.getString(R.string.favorites_tab_route_update)));
		
	}



	public void addFavoriteRoute(Context context) {
		busRoute.setFavorite(true);
		BusRouteDAO routeDAO = new BusRouteDAO(ApplicationDataBase.getSQLiteOpenHelper());
		routeDAO.setFavorite(busRoute);
		context.sendBroadcast(new Intent(context.getString(R.string.favorites_tab_route_update)));
		
	}



	public SimpleQueryWorker updateRouteSchedule() {
		
	/*	//query
		final RouteStopsWithTimesQuery query = new RouteStopsWithTimesQuery();
		query.addQueryInputParam(RouteStopsWithTimesQuery.InputParams.BUS_ROUTE_ID, busRoute.getRouteId());
		query.addQueryInputParam(RouteStopsWithTimesQuery.InputParams.DIR, busRoute.getRouteDir());
		
		//worker
		SimpleQueryWorker worker = new SimpleQueryWorker();
				
		
		
		//web service
		RouteStopsWithTimesWSQueryResResolver wsResHandler = new RouteStopsWithTimesWSQueryResResolver();
		IQueryHandler wsHandler = new SimpleWSQueryHandler(query, wsResHandler){
			
			@Override
			public void onPostQuery(){
				RouteStopsWithTimesWSQueryResResolver.QueryResult result = (org.niclab.vanbus.query.ws.RouteStopsWithTimesWSQueryResResolver.QueryResult) query.getQueryResult();
				busRoute.setStops(result.getStops());
				for(BusStop stop : busRoute.getStops()){
					stop.putTimes(busRoute, result.getTimes(stop.getStopId()));
				}
				
				busRoute.setScheduleLastPopulated(new Date());
				//put bus route to cache
				CacheUtils.saveBusRouteToCache(busRoute);
			}
		};
		
		worker.addAsyncQueryHandler(wsHandler);
		
		return worker;*/
		
		SimpleQueryWorker worker = loadBusStops();
		worker.removeSyncQueryHandler();
		return worker;
		
		
	
		
	}



	/**
	 * If curLat ==0 and curLng ==0, it will use MyLocationManager to get the current best estimation.
	 * @param curLat current latitude
	 * @param curLng current longitude
	 * @return the query worker to find the closest stops
	 */
	public SimpleQueryWorker findClosestStop(final double curLat, final double curLng) {
		final IQuery query = new ClosestBusStopsQuery();
		if(curLat ==0.0 && curLng ==0.0){
			query.addQueryInputParam(ClosestBusStopsQuery.InputParams.CURRENT_LNG, curLng);
			query.addQueryInputParam(ClosestBusStopsQuery.InputParams.CURRENT_LAT, curLat);
		}
		
		SimpleQueryWorker worker = new SimpleQueryWorker();
		
		ClosestBusStopsWSQueryResResolver resHandler = new ClosestBusStopsWSQueryResResolver();
		SimpleWSQueryHandler qHandler = new SimpleWSQueryHandler(query, resHandler){
			
			@Override
			public void onPreQuery(){
				if(curLat==0.0 && curLng==0.0){
					Location loc = VanBusApplication.getInstance().getMyLocationManager().getCurrentBestLocation(3000);
					query.addQueryInputParam(ClosestBusStopsQuery.InputParams.CURRENT_LNG, loc.getLongitude());
					query.addQueryInputParam(ClosestBusStopsQuery.InputParams.CURRENT_LAT, loc.getLatitude());
				}
			}
			@Override
			public void onPostQuery(){
				ClosestBusStopsWSQueryResResolver.QueryResult result = (org.niclab.vanbus.query.ws.ClosestBusStopsWSQueryResResolver.QueryResult) query.getQueryResult();
				List<BusStop> stops = result.getStops();
				HashSet<BusStop> allStops = new HashSet<BusStop>(busRoute.getStops());
				Iterator<BusStop> stopItr = stops.iterator();
				while(stopItr.hasNext()){
					if(!allStops.contains(stopItr.next()))
						stopItr.remove();
				}
			/*	for(BusStop stop:stops){
					if(!allStops.contains(stop))
						stops.remove(stop);
				}*/
				
			}
		};
		
		worker.addAsyncQueryHandler(qHandler);
		
		
		return worker;
		
		
	}
	

	
	public SimpleQueryWorker loadBusStops(){
		//query
		final RouteStopsWithTimesQuery query = new RouteStopsWithTimesQuery();
		query.addQueryInputParam(RouteStopsWithTimesQuery.InputParams.BUS_ROUTE_ID, busRoute.getRouteId());
		query.addQueryInputParam(RouteStopsWithTimesQuery.InputParams.DIR, busRoute.getRouteDir());

		//worker
		final SimpleQueryWorker worker = new SimpleQueryWorker();
		
		
		
	
		//Memory query handler
		IQueryHandler memHandler = new SimpleMemQueryHandler(query){

			@Override
			public void query() {
				
			

				long threshold = VanBusApplication.getInstance().getPreferences().getScheduleUpdateThreshold();

				if (!busRoute.needRepopulate(threshold))
					
				{
					Log.v(LOG_TAG,"populate route stops query is finished");
					query.setQueryFinished(true);

					//put the busRoute objec to cache
					CacheUtils.saveBusRouteToCache(busRoute);

				}
						
			}		
			
		};
		worker.addSyncQueryHandler(memHandler);
		//web service
		RouteStopsWithTimesWSQueryResResolver wsResHandler = new RouteStopsWithTimesWSQueryResResolver();
		
		IQueryHandler wsHandler = new SimpleWSQueryHandler(query, wsResHandler){
			@Override
			public void onPostQuery(){
				RouteStopsWithTimesWSQueryResResolver.QueryResult result = (org.niclab.vanbus.query.ws.RouteStopsWithTimesWSQueryResResolver.QueryResult)query .getQueryResult();
				busRoute.setStops(result.getStops());
				for(BusStop stop : busRoute.getStops()){
					stop.putTimes(busRoute, result.getTimes(stop.getStopId()));
				}
				
				busRoute.setScheduleLastPopulated(new Date());
				//put bus route to cache
				CacheUtils.saveBusRouteToCache(busRoute);
				
				//check the database if there are any favorite bus stops
				BusStopDAO busDao = new BusStopDAO(ApplicationDataBase.getSQLiteOpenHelper());
				busDao.checkFavoriteStops(busRoute.getStops());
				
			}
		};
		
		worker.addAsyncQueryHandler(wsHandler);
		
		return worker;
		
	}
	
	

}
